package com.cskaoyan.javase._2inner._3local._2usecase;

/**
 * 局部内部类经常使用在以下两个场景中：
 *      1.方法需要返回一个对象，返回值类型是引用数据类型时。
 *      方法需要返回一个对象时，可以在方法的局部位置写一个 局部内部类 继承/实现外部的类/接口，创建对象后作为返回值。这是因为方法的返回值可以是返回值类型的对象，也可以是子类对象（当返回值类型是引用数据类型时）。
 *
 *      2.方法需要传入一个对象，形参数据类型是引用数据类型时。
 *
 *      方法需要传入一个对象实参时，可以在调用方法的位置定义一个 局部内部类 来继承/实现外部的类/接口，创建对象后作为方法的实参传入。这是因为方法的实参可以是形参类型的对象，也可以子类对象（当返回值类型是引用数据类型时）。
 *
 * 使用局部内部类的优点：
 *      1.绝对对外界隐藏，封装。
 *      2.相比较于传统的定义类，然后创建对象，它相对更加简洁省事。
 *
 * 缺点：
 *      1.这个类是一次性的。
 * 综上，假如在局部位置需要一次性的使用某个对象
 * 可以使用局部内部类创建它
 * 但是如果多次在不同的方法中使用，使用局部内部类就得不偿失了。
 *
 * 以上,局部内部类的语法还是有些麻烦了,这是局部内部类使用的最大限制
 * 在实际开发中,很少直接使用局部内部类
 * 因为匿名内部类,Lambda表达式语法更简洁,基本取代了它.
 *
 * @since 17:50
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        method().test();
        method2().test();

        method(new IAImpl());
        // 定义局部内部类作为接口的实现类
        class IAImpl implements IA{
            @Override
            public void test() {
                System.out.println("我是局部内部类的接口子类实现,我更高级!");
            }
        }
        method(new IAImpl());
    }

    public static void method(IA ia){
        ia.test();
    }

    public static A method(){
        // return new A();
        // return new ASon();
        // 定义局部内部类,隐藏类
        class ASon extends A{
            @Override
            void test() {
                System.out.println("我是局部内部类的实现,我更加高级!");
            }
        }
        return new ASon();
    }

    public static BaseA method2(){
        // 定义局部内部类,用该局部内部类作为抽象类的实现,作为方法的返回值
        class BaseASon extends BaseA{
            @Override
            public void test() {
                System.out.println("我是抽象类的子类,局部内部类的实现!");
            }
        }
        return new BaseASon();
    }
}

class A {
    void test(){
        System.out.println("A");
    }
}
// 手写子类实现
class ASon extends A{
    @Override
    void test() {
        System.out.println("ASon");
    }
}

interface IA {
    void test();
}
class IAImpl implements IA{
    @Override
    public void test() {
        System.out.println("IAImpl");
    }
}
abstract class BaseA {
    public abstract void test();
}